package com.hly.tool.tree;

import com.matrixone.json.JSONArray;
import com.matrixone.json.JSONObject;
import matrix.util.MatrixException;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 数据层级类型
 *
 * @author ：Jack Hao
 * @date ：Created in 2021/7/19 21:22
 * @description：
 */
public class Tree3
{

    /**
     * 获取树结构 json 数据
     *
     * @param lists
     * @return
     */
    public static JSONArray getTreeJSONArray(List<List> lists, String levelColumn) throws Exception
    {

        JSONArray array = new JSONArray();
        for (int i = 0; i < lists.size(); i++)
        {
            List list_i = lists.get(i);
            //System.out.println("list_i  " + list_i.size());
            JSONArray oneTree = getOneTree(list_i, levelColumn);
            //System.out.println("oneTree i : " + i + " ---- " + oneTree);
            array.put(oneTree);
        }
        //System.out.println("array  " + array);
        return array;
    }


    /**
     * 获取树结构 json 数据
     *
     * @param lists
     * @return
     */
    public static String getTreeStr(List<List> lists, String levelColumn) throws Exception
    {
        return getTreeJSONArray(lists, levelColumn).toString();
    }


    /**
     * @param list
     * @return
     */
    private static JSONArray getOneTree(List list, String levelColumn) throws Exception
    {
        JSONArray treeArray = getTree(list, levelColumn);
        return treeArray;
    }


    /**
     * 获取树结构 json 数据
     *
     * @param mapList
     * @return
     * @throws Exception
     */
    private static JSONArray getTree(List<Map<String, String>> mapList, String levelColumn) throws Exception
    {
        JSONArray array = new JSONArray();
//        数据分组
        Map<Integer, List<Map<String, String>>> groupMap = getGroupData(mapList, levelColumn);

//        获取数据分组后的key 集合
        Set<Integer> keySet = groupMap.keySet();
        List<Integer> keyList = new ArrayList<Integer>(keySet);
        keyList = keyList.stream().sorted((a, b) -> a - b).collect(Collectors.toList());

        if (groupMap == null)
        {
            return array;
        } else
        {
            array = getLevelDataByGroupMap(groupMap, levelColumn);
        }
        return array;
    }


    /**
     * 数据分组
     *
     * @param mapList
     * @return
     */
    private static Map<Integer, List<Map<String, String>>> getGroupData(List<Map<String, String>> mapList, String levelColumn)
    {
        if (mapList == null || mapList.size() == 0)
        {
            return null;
        }

        Map<Integer, List<Map<String, String>>> groupMap = new HashMap<Integer, List<Map<String, String>>>();

        if (mapList == null || mapList.size() == 0)
        {
            return groupMap;
        }

        TreeSet<Integer> indexSet = new TreeSet<Integer>();
        for (int i = 0; i < mapList.size(); i++)
        {
            Map map_i = (Map) mapList.get(i);
            String level = (String) map_i.get(levelColumn);
            indexSet.add(level.length());
        }

        for (int len : indexSet)
        {
            List<Map<String, String>> levelList = new ArrayList<Map<String, String>>();
            for (int i = 0; i < mapList.size(); i++)
            {
                Map map_i = (Map) mapList.get(i);
                String level = (String) map_i.get(levelColumn);
                if (level.length() == len)
                {
                    levelList.add(map_i);
                }
            }
            groupMap.put(len, levelList);
        }
        return groupMap;
    }


    /**
     * @param groupMap
     * @throws Exception
     */
    private static JSONArray getLevelDataByGroupMap(Map<Integer, List<Map<String, String>>> groupMap, String levelColumn) throws Exception
    {
        JSONArray array = new JSONArray();
        Set<Integer> keySet = groupMap.keySet();
        List<Integer> keyList = new ArrayList<Integer>(keySet);

//        JDK 1.7 not support
        keyList = keyList.stream().sorted((a, b) -> a - b).collect(Collectors.toList());
        //System.out.println("keyList = " + keyList);

        JSONArray levelData = getLevelData(groupMap, keyList, array, null, levelColumn);
        //System.out.println("levelData = " + levelData);
        return levelData;
    }

    /**
     * @param groupMap
     * @param keyList
     * @param array
     * @param jsonObject
     * @return
     * @throws Exception
     */
    private static JSONArray getLevelData(Map<Integer, List<Map<String, String>>> groupMap, List<Integer> keyList, JSONArray array, JSONObject jsonObject, String levelColumn) throws Exception
    {
        int key = 0;
        String level = null;
        if (jsonObject == null)
        {
            key = keyList.get(0);
        } else
        {
            level = jsonObject.getString(levelColumn);
            key = level.length();
            int i = keyList.indexOf(key);
            if (i + 1 < keyList.size())
            {
                key = keyList.get(i + 1);

            } else
            {
                key = 999999999;
            }
        }

        List<Map<String, String>> maps = groupMap.get(key);
        if (maps == null || maps.size() == 0)
        {
            jsonObject.put("children", new JSONArray());
        } else
        {
            if (jsonObject == null)
            {
                for (int i = 0; i < maps.size(); i++)
                {
                    Map<String, String> map_i = maps.get(i);
                    JSONObject json_i = mapToJson(map_i);
                    array.put(json_i);
                    getLevelData(groupMap, keyList, array, json_i, levelColumn);
                }
            } else
            {
                JSONArray carray = new JSONArray();
                for (int i = 0; i < maps.size(); i++)
                {
                    Map<String, String> map_i = maps.get(i);
                    String clevel = map_i.get(levelColumn);
                    if (clevel.startsWith(level))
                    {
                        JSONObject json_i = mapToJson(map_i);
                        carray.put(json_i);
                        getLevelData(groupMap, keyList, carray, json_i, levelColumn);
                    }
                }
                jsonObject.put("children", carray);
            }
        }
        return array;
    }


    /**
     * map to json
     *
     * @param map
     * @return
     * @throws MatrixException
     */
    private static JSONObject mapToJson(Map map) throws MatrixException
    {
        JSONObject json = new JSONObject();
        Set set = map.keySet();
        Iterator iterator = set.iterator();
        while (iterator.hasNext())
        {
            String key = (String) iterator.next();
            String value = (String) map.get(key);
            json.put(key, value);
        }
        return json;
    }


    /**
     * @param resString
     * @return String
     * @throws
     * @Description format json data
     * @author
     * @date 2018/10/29-13:45
     */
    public static String responseFormat(String resString)
    {
        StringBuffer jsonForMatStr = new StringBuffer();
        int level = 0;
        for (int index = 0; index < resString.length(); index++)//
        {
            char c = resString.charAt(index);
            if (level > 0 && '\n' == jsonForMatStr.charAt(jsonForMatStr.length() - 1))
            {
                jsonForMatStr.append(getLevelStr(level));
            }
            switch (c)
            {
                case '{':
                case '[':
                    jsonForMatStr.append(c + "\n");
                    level++;
                    break;
                case ',':
                    jsonForMatStr.append(c + "\n");
                    break;
                case '}':
                case ']':
                    jsonForMatStr.append("\n");
                    level--;
                    jsonForMatStr.append(getLevelStr(level));
                    jsonForMatStr.append(c);
                    break;
                default:
                    jsonForMatStr.append(c);
                    break;
            }
        }
        return jsonForMatStr.toString();
    }


    /**
     * @param level
     * @return
     * @throws
     * @author
     * @date
     */
    private static String getLevelStr(int level)
    {
        StringBuffer levelStr = new StringBuffer();
        for (int levelI = 0; levelI < level; levelI++)
        {
            levelStr.append("\t");
        }
        return levelStr.toString();
    }


//    public static void main(String[] args)
//    {
//        try
//        {
//            File file = new File("C:\\Users\\KY08\\Desktop\\Library_10.xlsx");
//            //System.out.println("file = " + file);
//            MapList excelData = Excel.getExcelData(file);
//            //System.out.println("excelData = " + excelData);
//            String levelColumn = "\u4ea7\u54c1\u5206\u7ec4\u53f7\u3002";
//            List indexList = ListUtil.getIndexListByMapValue(excelData, levelColumn, 2);
//            //System.out.println("indexListByMapValue : " + indexList);
//
//            List<List> list = ListUtil.splitListByIndexList(excelData, indexList);
//            //System.out.println("list : " + list.size());
//
//            for (int i = 0; i < list.size(); i++)
//            {
//                List list_i = list.get(i);
//                //System.out.println("list_i : " + list_i.size());
//            }
//
//
//            JSONArray treeJSONArray = getTreeJSONArray(list, levelColumn);
//            //System.out.println("treeJSONArray : " + treeJSONArray);
////
////            //System.out.println(" responseFormat(); : "+ responseFormat(treeJSONArray.toString()));
//        } catch (Exception e)
//        {
//            e.printStackTrace();
//        }
//
//    }


}
